package com.lanchetech.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.bean.redission.LockCenter;
import com.lanchetech.bean.request.ShareActivityReq;
import com.lanchetech.bean.request.ShareDetailedReq;
import com.lanchetech.bean.response.BasePageResp;
import com.lanchetech.bean.response.BaseResp;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.task.ShareDetailedTask;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.common.util.ObjectUtil;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.ShareActivityService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

@Service
public class ShareActivityServiceImpl implements ShareActivityService {

    @Autowired
    private ShareActivityMapper shareActivityMapper;
    @Autowired
    private ShareActivitySpuMapper shareActivitySpuMapper;
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private ShareDetailedMapper shareDetailedMapper;
    @Autowired
    private UserCommissionMapper userCommissionMapper;
    @Autowired
    private OrderSkuMapper orderSkuMapper;
    @Autowired
    private CardFlowMapper cardFlowMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ShareDetailedTask shareDetailedTask;

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    public BaseResp editSharActivity(ShareActivity shareActivity) throws ResultCodeException {
        if (StringUtils.isBlank(shareActivity.getTitle())) {
            throw new ResultCodeException(ResultCode.SHARE_TITLE_IS_NULL);
        }
        if (shareActivity.getConfirmReceipt() == null) {
            throw new ResultCodeException(ResultCode.SHARE_PLEASE_SELECT);
        }
        // 新增
        if (shareActivity.getId() == null) {
            shareActivity.setCreated(new Date());
            shareActivityMapper.insertSelective(shareActivity);
            return new BaseResp();
        }
        // 编辑
        shareActivityMapper.insert(shareActivity);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<ShareActivityVo>> getShareActivity(ShareActivityReq shareActivityReq) {
        Page page = PageHelper.startPage(shareActivityReq.getPageNum(), shareActivityReq.getPageSize());
        // TODO :: VO展示视图数据  DTO数据传输
        List<ShareActivityVo> shareActivityVos = shareActivityMapper.findAllShareActivity(shareActivityReq);
        if (CollectionUtils.isNotEmpty(shareActivityVos)) {
            shareActivityVos.forEach(shareActivityVo -> {
                if (!shareActivityVo.isDeleted()) {
                    shareActivityVo.setSpuItemVOS(getBindSpu(shareActivityVo.getId()).getValue());
                }
            });
        }
        return PageHelpUtil.buildPage(shareActivityVos, page);
    }

    @Override
    public void bindSku(Set<ShareActivitySpu> shareActivitySpus, Long activityId, List<String> exceptionList) throws ResultCodeException {
        ShareActivity shareActivity = shareActivityMapper.getByShareActivityId(activityId);
        if (shareActivity == null || shareActivity.isDeleted()) {
            throw new ResultCodeException(ResultCode.SHARE_ACTIVITY);
        }
        if (shareActivity.isWhether()) {
            throw new ResultCodeException(ResultCode.SHARE_CANNOT_OPERATE_DURING_OPENING);
        }
        shareActivitySpus.forEach(shareActivitySpu -> {
            // 先判断ID是否存在
            if (shareActivitySpu.getId() != null) {
                ShareActivitySpuVo vo = shareActivitySpuMapper.getOneShareActivitySpuById(shareActivitySpu.getId());
                if (null != vo) {
                    // 如果存在则删除数据
                    vo.setDeleted(true);
                    shareActivitySpuMapper.updateByPrimaryKey(vo);
                    shareActivitySpu.setUpdated(new Date());
                }
            }
        });
        // 通过skuId 进行分组
        Set<Long> skuIds = shareActivitySpus.stream().map(ShareActivitySpu::getSkuId).collect(Collectors.toSet());
        // 根据活动ID skuIds 查找 是否存在
        List<ShareActivitySpu> list = shareActivitySpuMapper.getBySkuIds(activityId, skuIds);
        Map<Long, List<ShareActivitySpu>> groupBySkuId = list.stream().collect(Collectors.groupingBy(ShareActivitySpu::getSkuId));
        for (ShareActivitySpu activitySpu : shareActivitySpus) {
            // TODO true:固定金额   false:百分比
            if (!activitySpu.getType()) {
                activitySpu.setCommissionScale(activitySpu.getCommissionScale().divide(BigDecimal.valueOf(100)));
                activitySpu.setHiCoinScale(activitySpu.getHiCoinScale().divide(BigDecimal.valueOf(100)));
            }
            List<ShareActivitySpu> shareActivitySpuList = groupBySkuId.get(activitySpu.getSkuId());
            if (CollectionUtils.isNotEmpty(shareActivitySpuList)) {
                exceptionList.add("skuId: " + activitySpu.getSkuId() + ",已绑定其它活动,不能重复绑定");
                return;
            }
            String remark = ",设置的佣金+嗨币大于销售价,请重新计算,再进行绑定";
            if (activitySpu.getType()) {
                BigDecimal skuPrice = skuMapper.getSkuPriceById(activitySpu.getSkuId());
                if (activitySpu.getHiCoinScale().add(activitySpu.getCommissionScale()).compareTo(skuPrice) > 0) {
                    exceptionList.add("skuId:" + activitySpu.getSkuId() + remark);
                    return;
                }
            } else {
                if (activitySpu.getHiCoinScale().add(activitySpu.getCommissionScale()).compareTo(BigDecimal.valueOf(100)) > 0) {
                    exceptionList.add("skuId:" + activitySpu.getSkuId() + remark);
                    return;
                }
            }
            activitySpu.setShareActivityId(activityId);
        }
        if (CollectionUtils.isNotEmpty(shareActivitySpus)) {
            shareActivitySpuMapper.bindSpu(shareActivitySpus);
        }
    }

    @Override
    public void whether(Long id) throws ResultCodeException {
        ShareActivity shareActivity = shareActivityMapper.getByShareActivityId(id);
        if (shareActivity == null) {
            throw new ResultCodeException(ResultCode.SHARE_ACTIVITY);
        }
        if (shareActivity.isDeleted()) {
            throw new ResultCodeException(ResultCode.SHARE_ACTIVITY_IS_NULL);
        }
        if (!shareActivity.isWhether()) {
            if (shareActivity.isTerraceControl()) {
                throw new ResultCodeException(ResultCode.SHARE_FREEZE);
            }
            long count = shareActivitySpuMapper.getByShareActivityId(id);
            if (count < 1) {
                throw new ResultCodeException(ResultCode.SHARE_UNBOUND_ITEM);
            }
        }
        shareActivity.setWhether(!shareActivity.isWhether());
        shareActivityMapper.updateByPrimaryKey(shareActivity);
    }

    @Override
    public void removeSpu(Long shareActivitySpuId) throws ResultCodeException {
        // 查找该商家下分享赚 有无被平台冻结
        List<Long> longs = new ArrayList<>();
        longs.add(shareActivitySpuId);
        List<ShareActivitySpuVo> shareActivitySpu = shareActivitySpuMapper.getShareActivitySpuByIds(longs);
        if (CollectionUtils.isEmpty(shareActivitySpu)) throw new ResultCodeException(ResultCode.SHARE_PRODUCT_NOT_FOUND);
//        ShareActivitySpuVo vo = shareActivitySpuMapper.getOneShareActivitySpuById(shareActivitySpuId);
//        if (null == vo) throw new ResultCodeException(ResultCode.SHARE_PRODUCT_NOT_FOUND);
//        if (vo.isTerraceControl()) {
//            throw new ResultCodeException(ResultCode.SHARE_ITEM_UNABLE_REMOVE);
//        }
        shareActivitySpuMapper.removeSpuBySpuId(shareActivitySpuId, true);
    }

    @Override
    public void freeze(Long id) throws ResultCodeException {
        ShareActivity shareActivity = shareActivityMapper.getByShareActivityId(id);
        if (shareActivity == null) {
            throw new ResultCodeException(ResultCode.SHARE_ACTIVITY);
        }
        shareActivity.setWhether(false);
        shareActivity.setTerraceControl(true);
        shareActivityMapper.updateByPrimaryKey(shareActivity);
    }

    @Override
    public ResultData<List<SpuItemVO>> getBindSpu(Long shareActivityId) {
        // 查找当前活动所有未解绑的商品
        List<ShareActivitySpuVo> shareActivityVos = shareActivitySpuMapper.finAllShareActivitySpuByActivityId(shareActivityId);
        CollectionUtils.isEmpty(shareActivityVos);
        List<Long> spuIds = shareActivityVos.stream().map(ShareActivitySpuVo::getSpuId).collect(Collectors.toList());
        if (spuIds.size() == 0) {
            return new ResultData<>();
        }
        List<Spu> spuList = spuMapper.findAllByIds(spuIds);
        List<SpuItemVO> copy = ObjectUtil.copy(spuList, SpuItemVO.class);
        for (SpuItemVO spu : copy) {
            List<ShareActivitySpuVo> shareActivitySpuVos = new ArrayList<>();
            shareActivityVos.forEach(shareActivitySpuVo -> {
                if (spu.getId().equals(shareActivitySpuVo.getSpuId())) {
                    // 查找sku信息
                    ShareSkuVo shareSkuVo = skuMapper.getSkuById(shareActivitySpuVo.getSkuId());
                    // 放入sku信息
                    shareActivitySpuVo.setShareSkuVo(shareSkuVo);
//                    shareActivitySpuVo.setSpuName(shareSkuVo.getSpuName());
//                    shareActivitySpuVo.setSpuMainImage(shareSkuVo.getSpuMainImage());
//                    shareActivitySpuVo.setSkuPrice(shareSkuVo.getPrice());
//                    shareActivitySpuVo.setSpecNames(shareSkuVo.getSpecNames());
//                    shareActivitySpuVo.setSpecValues(shareSkuVo.getSpecValues());
                    shareActivitySpuVos.add(shareActivitySpuVo);
                }
                spu.setShareActivitySpuVoList(shareActivitySpuVos);
            });
        }
        return new ResultData<>(copy);
    }

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public ResultData<List<ShareActivityVo>> miniGetShareActivity(ShareActivityReq shareActivityReq) {
        // 放入缓存
        ValueOperations<String, List<ShareActivityVo>> operations = redisTemplate.opsForValue();
        // 生成key
        String key = "ShareActivityVo:";
        // 根据key查找是否存在
        List<ShareActivityVo> shareActivityVos = operations.get(key);
        // 不存在查找全部分享赚存储redis
        if (shareActivityVos == null) {
            List<ShareActivityVo> shareActivitys = shareActivityMapper.findAllShareActivity(shareActivityReq);
            operations.set(key, shareActivitys, 60, TimeUnit.MINUTES);
        }
        return new ResultData<>(shareActivityVos);
    }

    @Override
    public ResultData<ShareActivityVo> getShareActivitySpu(Long shareActivityId) throws ResultCodeException {
        ValueOperations<String, List<ShareActivityVo>> operations = redisTemplate.opsForValue();
        List<ShareActivityVo> shareActivityVos = operations.get("ShareActivityVo:");
        if (CollectionUtils.isNotEmpty(shareActivityVos)) {
            for (ShareActivityVo shareActivityVo : shareActivityVos) {
                if (shareActivityVo.isTerraceControl()) {
                    throw new ResultCodeException(ResultCode.SHARE_COMPLETED);
                }
                // 判断是否对应该分享赚
                if (shareActivityVo.getId().equals(shareActivityId)) {
                    // 查找该分享赚下所绑定的Spu+Sku
                    List<ShareActivitySpuVo> vos = shareActivitySpuMapper.getSpuByShareActivityId(shareActivityVo.getId(), false);
                    // 如果为null就返回
                    if (CollectionUtils.isEmpty(vos)) return new ResultData<>();
                    // 根据skuId进行分组
                    List<Long> skuIds = vos.stream().map(ShareActivitySpuVo::getSkuId).collect(Collectors.toList());
                    // 查找所有对应的sku
                    List<ShareSkuVo> skus = skuMapper.getAllByIds(skuIds);
                    // 判断
                    if (CollectionUtils.isNotEmpty(skus)) {
                        // 循环遍历
                        skus.forEach(sku -> {
                            // 绑定的sku
                            for (ShareActivitySpuVo shareActivitySpuVo : vos) {
                                // 是否相等
                                if (sku.getId().equals(shareActivitySpuVo.getSkuId())) {
                                    // TODO true:固定金额  false:百分比
                                    if (shareActivitySpuVo.getType()) {
                                        sku.setCommissionScale(shareActivitySpuVo.getCommissionScale());
                                        sku.setHiCoinScale(shareActivitySpuVo.getHiCoinScale());
                                    } else {
                                        sku.setCommissionScale(sku.getPrice().multiply(shareActivitySpuVo.getCommissionScale()).setScale(2, RoundingMode.HALF_DOWN));
                                        sku.setHiCoinScale(sku.getPrice().multiply(shareActivitySpuVo.getHiCoinScale()).setScale(2, RoundingMode.HALF_UP));
                                    }
                                }
                            }
                        });

                        shareActivityVo.setShareSkuVos(skus);
                    }
                }
                return new ResultData<>(shareActivityVo);
            }
        }
        return new ResultData<>();
    }

    @Override
    public BaseResp deleteShareById(Long shareActivityId) throws ResultCodeException {
        ShareActivity shareActivity = shareActivityMapper.getByShareActivityId(shareActivityId);
        if (null == shareActivity) throw new ResultCodeException(ResultCode.SHARE_ACTIVITY);
        shareActivity.setDeleted(true);
        // 删除分享赚
        shareActivityMapper.insert(shareActivity);
        // 删除分享赚商品
        shareActivitySpuMapper.updateDeletedByShareActivityId(shareActivityId, true);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<ShareDetailedVo>> getShareDetailed(ShareDetailedReq req) {
        Page page = PageHelper.startPage(req.getPageNum(), req.getPageSize());
        List<ShareDetailed> shareDetailed = shareDetailedMapper.findAll(req);
        List<ShareDetailedVo> vo = ObjectUtil.copy(shareDetailed, ShareDetailedVo.class);
        return PageHelpUtil.buildPage(vo, page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void freezeOrNot(Long id) throws ResultCodeException {
        ShareDetailed shareDetailed = shareDetailedMapper.selectByPrimaryKey(id);
        if (shareDetailed == null) {
            throw new ResultCodeException(ResultCode.SHARE_SHARE_RECORDS);
        }
        if (shareDetailed.isIssued()) {
            throw new ResultCodeException(ResultCode.SHARE_SHARE_ISSUED);
        }
        OrderSku orderSku = orderSkuMapper.findOneById(shareDetailed.getOrderSkuId());
        shareDetailed.setFreeze(!shareDetailed.getFreeze());
        // 如果是冻结直接更改
        if (shareDetailed.getFreeze()) {
            shareDetailedMapper.updateByPrimaryKey(shareDetailed);
            // 移除定时任务
            shareDetailedTask.remove(shareDetailed.getId());
        } else {
            // 如果是解冻重新加入定时任务
            if (shareDetailed.getReceiptTime() != null) {
                // 当前时间在发放奖励之后 则重新加入定时任务
                if (shareDetailed.getReceiptTime().after(new Date())) {
                    shareDetailedTask.addTask(ObjectUtil.copy(shareDetailed, ShareDetailedVo.class));
                } else {
                    provide(shareDetailed, orderSku);
                }
                // 移除定时任务
                shareDetailedTask.remove(shareDetailed.getId());
                shareDetailed.setIssued(true);
                shareDetailedMapper.updateByPrimaryKey(shareDetailed);
            }
        }
    }

    @Override
    public void provide(ShareDetailed shareDetailed, OrderSku orderSku) {
        // 直接发放佣金
        if (shareDetailed.getType() == ShareRebateEnum.COMMISSION.getCode()) {
            provideComm(shareDetailed, orderSku);
        }
        // 直接发放嗨币
        if (shareDetailed.getType() == ShareRebateEnum.HICOIN.getCode()) {
            provideHiCoin(shareDetailed, orderSku);
        }
    }

    private void provideHiCoin(ShareDetailed shareDetailed, OrderSku orderSku) {
        // 收益嗨币
        BigDecimal hiCoinRebate = shareDetailed.getHiCoinRebate();
        User user = userMapper.selectByPrimaryKey(shareDetailed.getBeneficiaryUserId());
        BigDecimal cardPoint = user.getCardPoint().add(hiCoinRebate);
        userMapper.updateCardPointById(cardPoint, user.getId());
        cardFlowMapper.insert(CardFlow.builder()
                .userId(shareDetailed.getBeneficiaryUserId())
                .amount(hiCoinRebate)
                .tradeType(CardTradeTypeEnum.SHARE_HI_COIN_REBATE.getTradeType())
                .type((byte) 0)
                .cardPoint(cardPoint)
                .relateId(orderSku.getSkuId())
                .remark("分享好友下单,获得嗨币收益:" + shareDetailed.getHiCoinRebate())
                .createdAt(new Date())
                .performance(shareDetailed.getAmount())
                .build());
    }

    private void provideComm(ShareDetailed shareDetailed, OrderSku orderSku) {
        userCommissionMapper.insert(
                UserCommission.builder()
                        .superiorId(shareDetailed.getBeneficiaryUserId())
                        .subordinateId(shareDetailed.getProviderUserId())
                        .orderSkuId(shareDetailed.getOrderSkuId())
                        .commission(shareDetailed.getCommissionRebate())
                        .remark("用户通过您分享下单,获得收益佣金:" + shareDetailed.getCommissionRebate())
                        .relateId(orderSku.getSkuId())
                        .type(UserCommissionTypeEnum.SHARE_COMMISSION.getType())
                        .status(UserCommissionStatusEnum.ISSUED.getStatus())
                        .createdAt(new Date())
                        .amount(shareDetailed.getAmount())
                        .identityType((byte) -1)
                        .businessType(UserCommissionBusinessTypeEnum.USER.getType())
                        .shopId(shareDetailed.getTenantId())
                        .fromType((byte) 0)
                        .build());
    }

    @Override
    public void addTask(ShareDetailedVo shareDetailed) {
        Lock lock = LockCenter.getLock(shareDetailed.getClass());
        try {
            lock.lock();
            if (shareDetailed.isIssued()) {
                return;
            }
            OrderSku orderSku = orderSkuMapper.findOneById(shareDetailed.getOrderSkuId());
            if (orderSku == null) {
                return;
            }
            // 修改分享赚返佣状态
            shareDetailed.setIssued(true);
            shareDetailed.setUpdated(new Date());
            shareDetailedMapper.updateByPrimaryKey(shareDetailed);
            // 发放佣金/嗨币
            provide(shareDetailed, orderSku);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public ResultData<BasePageResp<ShareDetailedVo>> findAllShareDetailed(ShareDetailedReq shareDetailedReq) {
        Page page = PageHelper.startPage(shareDetailedReq.getPageNum(), shareDetailedReq.getPageSize());
        List<ShareDetailed> vos = shareDetailedMapper.findAll(shareDetailedReq);
        return PageHelpUtil.buildPage(ObjectUtil.copy(vos, ShareDetailedVo.class), page);
    }

}
